import urllib
import db

class SimplePaginator(object):
    def __init__(self, query, num_per_page, page=1):
        self.query = query
        self.num_per_page = num_per_page
        if page < 1:
            page = 1
        self.page = page
    
    def get_page_offset(self):          
        offset = self.page - 1
        return (self.page, offset)

    #do pagination
    def get_page_info(self, next=False):
        page_num, offset = self.get_page_offset()
        page = {}
        page['prev'] = page['next'] = False
    
        if offset > 0:
            page['prev'] = True
            page['prev_page'] = page_num - 1
        if next == True:
            page['next'] = True
            page['next_page'] = page_num + 1
    
        return page

    def get_page_objects(self):
        page_num, offset = self.get_page_offset()
        objects = self.query.fetch(self.num_per_page+1, self.num_per_page*offset)
        #pagination info
        page = self.get_page_info(len(objects) > self.num_per_page)
        objects = objects[0:self.num_per_page]
        return (objects, page)    

class BasePaginator(object):
    def __init__(self, request, query, num_per_page, page_qs='page', qs_filter=None):
        self.request = request
        self.query = query
        self.num_per_page = num_per_page
        self.page_qs = page_qs
        self.qs_filter = qs_filter
    
    def change_query_str(self, name, value):
        post = self.request.POST.copy()
        get = self.request.GET.copy()
        get.update(post)
        
        #filter some query string parameters
        if self.qs_filter:
            get = self.qs_filter(get)
        
        get[name] = str(value)
        query_str = get.urlencode() 
        return (self.request.path + '?' + query_str, query_str)

    def get_page_offset(self):
        try:
            page = int(self.request.REQUEST.get(self.page_qs, 1))
            if page < 1:
                page = 1
        except:
            page = 1
          
        offset = page - 1
        return (page, offset)

    #do pagination
    def get_page_info(self, next=False):
        page_num, offset = self.get_page_offset()
        page = {}
        page['prev'] = page['next'] = False
    
        if offset > 0:
            page['prev'] = True
            page['prev_page'] = page_num - 1
            page['prev_page_url'], page['prev_page_qs'] = self.change_query_str(self.page_qs, page['prev_page'])
        if next == True:
            page['next'] = True
            page['next_page'] = page_num + 1
            page['next_page_url'], page['next_page_qs'] = self.change_query_str(self.page_qs, page['next_page'])
    
        return page

    def get_page_objects(self):
        page_num, offset = self.get_page_offset()
        offset = self.num_per_page*offset
        
        next = True
        
        #Datastore limitation
        if offset >= 1000:
            offset = 1000
            next = False
        
        objects = self.query.fetch(self.num_per_page+1, offset)
        
        if next == True:
            next = len(objects) > self.num_per_page
        
        #pagination info
        page = self.get_page_info(next)
        objects = objects[0:self.num_per_page]
        return (objects, page)
    
class Paginator(BasePaginator):
    def __init__(self, request, model, filters=[], num_per_page=10, page_qs='page', qs_filter=None):
        query = db.build_query(cls=model, filters=filters)
        BasePaginator.__init__(self, request, query, num_per_page, page_qs, qs_filter)
        